﻿using MvvmCross.Core.Views;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;

namespace Sidvall.UI.Views
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "ViewFinder")]
    public class FolderViewFinder : IMvxViewFinder
    {
        #region Public Members

        #region GetViewType

        public System.Type GetViewType(System.Type viewModelType)
        {
            if (viewModelType == null)
                return null;
            var view = Sidvall.SystemContext.Current.TypeCache.GetTypeFromCache(viewModelType.FullName);
            if (view != null)
                return view;
            view = GetViewType(viewModelType, Sidvall.SystemContext.Current.TypeCache.Assemblies);
            if (view != null)
                return view;
            var assemblies = Sidvall.SystemContext.Current.CodeManager.GetAssembliesAsync().Result;
            view = GetViewType(viewModelType, assemblies);
            if (view != null)
                return view;
            return null;
        }

        #endregion

        #region SetFolderPathAsync

        public async Task SetFolderPathAsync(string folderPath)
        {
            await Sidvall.SystemContext.Current.TypeCache.AddAssembliesAsync(folderPath);
        }
        public async Task SetFolderPathAsync(string folderPath, System.Collections.Generic.IEnumerable<string> searchPatterns, Sidvall.IO.SearchOption searchOption)
        {
            await Sidvall.SystemContext.Current.TypeCache.AddAssembliesAsync(folderPath, searchPatterns, searchOption);
        }

        #endregion

        #endregion
        #region Private Members

        #region GetViewType

        private static System.Type GetViewType(System.Type viewModelType, IEnumerable<Assembly> assemblies)
        {
            if (assemblies == null)
                return null;
            foreach (var assembly in assemblies)
            {
                var viewTypeNames = Sidvall.SystemContext.Current.CodeManager.GetAssemblyTypeNames(assembly, true, false, true, typeof(IMvxView).GetTypeInfo());
                if ((viewTypeNames != null) && (viewTypeNames.Length > 0))
                {
                    foreach (var viewTypeName in viewTypeNames)
                    {
                        var view = Sidvall.SystemContext.Current.CodeManager.GetType(viewTypeName, assembly);
                        if (view == null)
                            continue;
                        var viewModelPropertyInfo = (from o in Sidvall.SystemContext.Current.CodeManager.GetProperties(view, false, false, null, "ViewModel")
                                                     select o).FirstOrDefault();
                        if ((viewModelPropertyInfo != null) && (viewModelPropertyInfo.PropertyType == viewModelType))
                        {
                            Sidvall.SystemContext.Current.TypeCache.AddType(viewModelType.FullName, view);
                            return view;
                        }
                    }
                }
            }
            return null;
        }

        #endregion

        #endregion
    }
}
